package com.qcs.ando.manage;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.util.Log;

/** ͼƬͳһ������ */
public class ImageManager extends Manager {
    public ImageManager(Context context) {
        super(context);
    }

    /** ȡ���Context������ */
    public void destory() {
        mContext = null;
    }

    /**
     * @param assets
     *            ͼƬ��assets���·��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4Assets(String assets)
            throws IOException {
        Log.i(TAG, "create " + assets + " at assets.");
        InputStream is = null;
        Bitmap bitmap = null;

        try {
            is = mContext.getAssets().open(assets);
            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            if (null != is) {
                is.close();
                is = null;
            }

            System.gc();
        }

        return bitmap;
    }

    /**
     * @param res
     *            ͼƬ��res���·��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4Res(int res)
            throws IOException {
        Log.i(TAG, "create " + res + " at res.");
        InputStream is = null;
        Resources resources = null;
        Bitmap bitmap = null;

        try {
            resources = mContext.getResources();
            // ʹ��decodeResource������Դ�ļ�
            // decodeResource��������ͼƬ���ڷ��ࣨmdpi��hdpi��������ͬ���Ż���
            // ��ͬ�ڲ�����ֱ��������Դ�ļ���
            bitmap = BitmapFactory.decodeResource(resources, res);

            // ʹ�����������������Դ�ļ��������ͼƬ�����κ��Ż���
//            is = resources.openRawResource(res);
//            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            if (null != resources) {
                resources = null;
            }

            if (null != is) {
                is.close();
                is = null;
            }

            System.gc();
        }

        return bitmap;
    }

    /**
     * ����BitmapFactory.Options
     * 
     * @param assets
     *            ͼƬ��assets���·��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4AssetsByOption(String assets) throws IOException {
        return createBitmap4AssetsByOption(assets, 1);
    }

    /**
     * ����BitmapFactory.Options������������fraction��������ͼƬ
     * 
     * @param assets
     *            ͼƬ��assets���·��
     * @param fraction
     *            ��ͼƬ����fraction��֮һ��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4AssetsByOption(String assets, int fraction)
            throws IOException {
        Log.i(TAG, "create " + assets + " at assets.");
        InputStream is = null;
        Bitmap bitmap = null;

        BitmapFactory.Options options = null;

        try {
            options = getBitmapOptioins(fraction);
            is = mContext.getAssets().open(assets);
            bitmap = BitmapFactory.decodeStream(is, null, options);
        } finally {
            if (null != options) {
                options = null;
            }

            if (null != is) {
                is.close();
                is = null;
            }

            System.gc();
        }

        return bitmap;
    }

    /**
     * ����BitmapFactory.Options��ʹ�����С��������ͼƬ�� ����Matrix��ԭ��<br>
     * ������ʹ�ã�ʹ�ô˷�����ռ�ô����ڴ档
     * 
     * @param assets
     *            ͼƬ��assets���·��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    @Deprecated
    public Bitmap createBitmap4AssetsByOptionMatrix(String assets, int fraction)
            throws IOException {
        Log.i(TAG, "create " + assets + " at assets.");
        InputStream is = null;
        Bitmap bitmap = null;

        BitmapFactory.Options options = null;

        try {
            options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;

            is = mContext.getAssets().open(assets);
            bitmap = BitmapFactory.decodeStream(is, null, options);

            if (options.mCancel || options.outWidth == -1
                    || options.outHeight == -1) {

                throw new IOException("options.inJustDecodeBounds == true");
            }

            float originalW = options.outWidth;
            float originalH = options.outHeight;

            bitmap = createBitmap4AssetsByOption(assets, fraction);

            int optimizeW = bitmap.getWidth();
            int optimizeH = bitmap.getHeight();

            float scaleW = originalW / optimizeW;
            float scaleH = originalH / optimizeH;

            Matrix matrix = new Matrix();

            // ����ͼƬ����
            matrix.postScale(scaleW, scaleH);

            // �����µ�ͼƬ
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, optimizeW, optimizeH,
                    matrix, true);
        } finally {
            if (null != options) {
                options = null;
            }

            if (null != is) {
                is.close();
                is = null;
            }

            System.gc();
        }

        return bitmap;
    }

    /**
     * @param path
     *            ͼƬ�ڱ��ص�·����������SD����/data/data/packagename/Ŀ¼�С�
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4Native(String path)
            throws IOException {
        Log.i(TAG, "create " + path + " at assets.");

        return createBitmap(new FileInputStream(path), null);
    }

    /**
     * @param path
     *            ͼƬ�ڱ��ص�·����������SD����/data/data/packagename/Ŀ¼��
     *            ��������BitmapFactory.Options��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4NativeByOptions(String path)
            throws IOException {
        Log.i(TAG, "create " + path + " at assets.");

        return createBitmap(new FileInputStream(path), getBitmapOptioins(1));
    }

    /**
     * @param path
     *            ͼƬ�ڱ��ص�·����������SD����/data/data/packagename/Ŀ¼�С�
     * @param fraction
     *            ��ͼƬ����fraction��֮һ��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap4NativeByOptions(String path, int fraction)
            throws IOException {
        Log.i(TAG, "create " + path + " at assets.");

        return createBitmap(new FileInputStream(path),
                getBitmapOptioins(fraction));
    }

    /**
     * @param assetss
     *            ͼƬ���ϣ�������assets�ļ����ڡ�
     * @return ����ָ��·����Bitmap
     */
    public List<Bitmap> createBitmaps4Assets(List<String> assetss) {
        return createBitmaps4AssetsByOptions(assetss, 0, null);
    }

    /**
     * @param assetss
     *            ͼƬ���ϣ�������assets�ļ����ڡ�
     *            ��������BitmapFactory.Options��
     * @return ����ָ��·����Bitmap
     */
    public List<Bitmap> createBitmaps4AssetsByOptions(List<String> assetss) {
        return createBitmaps4AssetsByOptions(assetss, 1, null);
    }

    /**
     * @param assetss
     *            ͼƬ���ϣ�������assets�ļ����ڡ�
     * @param fraction
     *            ������ͼƬ����fraction��֮һ����Ϊ0�����Ż�ͼƬ
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ����ָ��·����Bitmap����
     */
    public List<Bitmap> createBitmaps4AssetsByOptions(List<String> assetss,
            int fraction, CreateBitmapException e) {
        List<String> pathList = assetss;

        List<Bitmap> bms = new ArrayList<Bitmap>();

        for (String path : pathList) {
            Log.i(TAG, "create " + path + " at assets.");

            try {
                Bitmap bitmap = createBitmap4AssetsByOption(path, fraction);
                bms.add(bitmap);
            } catch (FileNotFoundException e1) {
                if (null != e) {
                    e.ioe(path);
                }
            } catch (IOException e2) {
                if (null != e) {
                    e.ioe(path);
                }
            }
        }

        pathList = null;

        return bms;
    }

    /**
     * @see #createBitmapCache4AssetsByOptions(List, CreateBitmapException)
     */
    public ImageCacheManager createBitmapCache4AssetsByOptions(
            String[] assetss, CreateBitmapException e) {
        List<String> pathList = Arrays.asList(assetss);

        return createBitmapCache4AssetsByOptions(pathList, 1, 0, e);
    }

    /**
     * @see #createBitmapCache4AssetsByOptions(List, CreateBitmapException)
     */
    public ImageCacheManager createBitmapCache4AssetsByOptions(
            String[] assetss, int fraction, int cacheSize,
            CreateBitmapException e) {
        List<String> pathList = Arrays.asList(assetss);

        return createBitmapCache4AssetsByOptions(pathList, fraction, cacheSize,
                e);
    }

    /**
     * ΪͼƬ���ϴ���һ��ͼƬ�����������<br>
     * һ����������Ϊ{@link ImageCacheManager#HARD_CACHE_CAPACITY}��<br>
     * ����BitmapFactory.Options��ͼƬ�����������Ż���
     * 
     * @param assetss
     *            ͼƬ���ϣ�������assets�ļ����ڡ�
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ��������Bitmap��һ��ͼƬ������
     * @see {@link ImageCacheManager}: ͼƬ������?���ڶ�������
     */
    public ImageCacheManager createBitmapCache4AssetsByOptions(
            List<String> assetss, CreateBitmapException e) {
        return createBitmapCache4AssetsByOptions(assetss, 1, 0, e);
    }

    /**
     * 
     * ΪͼƬ���ϴ���һ��ͼƬ�����������
     * 
     * @param assetss
     *            ͼƬ���ϣ�������assets�ļ����ڡ�
     * @param fraction
     *            ����BitmapFactory.Options������ͼƬ�����Ż���<br>
     *            ������fraction��֮һ����Ϊ0�����Ż�ͼƬ
     * @param cacheSize
     *            һ�����������
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ��������Bitmap��һ��ͼƬ������
     * @see {@link ImageCacheManager}: ͼƬ������?���ڶ�������
     */
    public ImageCacheManager createBitmapCache4AssetsByOptions(
            List<String> assetss, int fraction, int cacheSize,
            CreateBitmapException e) {
        List<String> assetsList = assetss;

        ImageCacheManager icm = new ImageCacheManager(cacheSize);

        for (String assets : assetsList) {
            Log.i(TAG, "create " + assets + " at assets.");

            try {
                Bitmap bitmap = createBitmap4AssetsByOption(assets, fraction);
                icm.putBitmap(assets, bitmap);
            } catch (FileNotFoundException e1) {
                if (null != e) {
                    e.ioe(assets);
                }
            } catch (IOException e2) {
                if (null != e) {
                    e.ioe(assets);
                }
            }
        }

        assetsList = null;

        return icm;
    }

    /**
     * @param path
     *            ͼƬ�ڱ��ص�·����������SD����/data/data/packagename/Ŀ¼�С�
     * @return ����ָ��·����Bitmap
     */
    public List<Bitmap> createBitmaps4Native(List<String> paths) {
        return createBitmaps4NativeByOptions(paths, 0, null);
    }

    /**
     * @param path
     *            ͼƬ�ڱ��ص�·����������SD����/data/data/packagename/Ŀ¼��
     *            ��������BitmapFactory.Options��
     * @return ����ָ��·����Bitmap
     */
    public List<Bitmap> createBitmaps4NativeByOptions(List<String> paths) {
        return createBitmaps4NativeByOptions(paths, 1, null);
    }

    /**
     * @param paths
     *            ͼƬ���ϣ�������SD����/data/data/packagename/Ŀ¼�С�
     * @param fraction
     *            ������ͼƬ����fraction��֮һ����Ϊ0�����Ż�ͼƬ
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ����ָ��·����Bitmap����
     */
    public List<Bitmap> createBitmaps4NativeByOptions(List<String> paths,
            int fraction, CreateBitmapException e) {
        List<String> pathList = paths;

        List<Bitmap> bms = new ArrayList<Bitmap>();

        for (String path : pathList) {
            Log.i(TAG, "create " + path);

            try {
                Bitmap bitmap = createBitmap(new FileInputStream(path),
                        getBitmapOptioins(fraction));
                bms.add(bitmap);
            } catch (FileNotFoundException e1) {
                if (null != e) {
                    e.ioe(path);
                }
            } catch (IOException e2) {
                if (null != e) {
                    e.ioe(path);
                }
            }
        }

        pathList = null;

        return bms;
    }

    /**
     * @see #createBitmapCache4NativeByOptions(List, CreateBitmapException)
     */
    public ImageCacheManager createBitmapCache4NativeByOptions(
            String[] paths, CreateBitmapException e) {
        List<String> pathList = Arrays.asList(paths);

        return createBitmapCache4NativeByOptions(pathList, 1, 0, e);
    }

    /**
     * @see #createBitmapCache4NativeByOptions(List, CreateBitmapException)
     */
    public ImageCacheManager createBitmapCache4NativeByOptions(
            String[] paths, int fraction, int cacheSize, CreateBitmapException e) {
        List<String> pathList = Arrays.asList(paths);

        return createBitmapCache4NativeByOptions(pathList, fraction, cacheSize,
                e);
    }

    /**
     * ΪͼƬ���ϴ���һ��ͼƬ�����������<br>
     * һ����������Ϊ{@link ImageCacheManager#HARD_CACHE_CAPACITY}��<br>
     * ����BitmapFactory.Options��ͼƬ�����������Ż���
     * 
     * @param paths
     *            ͼƬ���ϣ�������SD����/data/data/packagename/Ŀ¼�С�
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ��������Bitmap��һ��ͼƬ������
     * @see {@link ImageCacheManager}: ͼƬ������?���ڶ�������
     */
    public ImageCacheManager createBitmapCache4NativeByOptions(
            List<String> paths, CreateBitmapException e) {
        return createBitmapCache4NativeByOptions(paths, 1, 0, e);
    }

    /**
     * 
     * ΪͼƬ���ϴ���һ��ͼƬ�����������
     * 
     * @param paths
     *            ͼƬ���ϣ�������SD����/data/data/packagename/Ŀ¼�С�
     * @param fraction
     *            ����BitmapFactory.Options������ͼƬ�����Ż���<br>
     *            ������fraction��֮һ����Ϊ0�����Ż�ͼƬ
     * @param cacheSize
     *            һ�����������
     * @param e
     *            ����Bitmap��������쳣����ͼƬ������
     * @return ��������Bitmap��һ��ͼƬ������
     * @see {@link ImageCacheManager}: ͼƬ������?���ڶ�������
     */
    public ImageCacheManager createBitmapCache4NativeByOptions(
            List<String> paths, int fraction, int cacheSize,
            CreateBitmapException e) {
        List<String> pathList = paths;

        ImageCacheManager icm = new ImageCacheManager(cacheSize);

        for (String path : pathList) {
            Log.i(TAG, "create " + path);

            try {
                Bitmap bitmap = createBitmap(new FileInputStream(path),
                        getBitmapOptioins(fraction));
                icm.putBitmap(path, bitmap);
            } catch (FileNotFoundException e1) {
                if (null != e) {
                    e.ioe(path);
                }
            } catch (IOException e2) {
                if (null != e) {
                    e.ioe(path);
                }
            }
        }

        pathList = null;

        return icm;
    }

    /**
     * @param assets
     *            ͼƬ��assets���·��
     * @return ����ָ��·����Bitmap
     * @throws IOException
     *             ����ʧ��
     */
    public Bitmap createBitmap(InputStream in, Options op)
            throws IOException {
        InputStream is = null;
        Bitmap bitmap = null;

        BitmapFactory.Options options = null;

        try {
            is = in;
            options = op;

            bitmap = BitmapFactory.decodeStream(is, null, options);
        } finally {
            if (null != options) {
                options = null;
            }

            if (null != is) {
                is.close();
                is = null;
            }

            System.gc();
        }

        return bitmap;
    }

    /**
     * ���ò��õ�BitmapFactory.Options��
     * 
     * @param inSampleSize
     *            �����С����֮һ����Ϊ0ʱ������null��
     * @return BitmapFactory.Options
     */
    private BitmapFactory.Options getBitmapOptioins(int inSampleSize) {
        if (0 == inSampleSize)
            return null;

        BitmapFactory.Options options = new BitmapFactory.Options();

        // ����ͼƬ����ͼƬ��߾���СinSampleSize��֮һ����
        // ͬʱ�ڴ�ռ�м���imSamplaySize��֮һ��
        options.inSampleSize = inSampleSize;

        // ����ͼƬ��ֻ����ͼƬ�Ŀ�ߣ����õ�������Ϣ�������ݱ�����Options��
        options.inJustDecodeBounds = false;

        // ����ͼƬ��ȥ������
        options.inDither = false;

        // ����ͼƬ�������ֽ����ʽ���н���
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        return options;
    }

    /** ����Bitmap�����쳣 */
    interface CreateBitmapException {

        /**
         * ��������������쳣���ļ������ڡ�
         * 
         * @param path
         *            �ļ�·��
         */
        public void ioe(String path);
    }
}
